<?php

namespace App\Web\Model;

use EchoPHP\Facades\Db;
use EchoPHP\Validator\Validator;


/**
 * Class Role
 * 角色管理相关业务逻辑
 * @package App\Web\Model
 */
class Role extends Model {
    public $rightsLength = 20; //权限code长度

    /**
     * 获取角色列表数量统计
     */
    public function getRoleListCount($search = []) {
        $field = 'count(1) as count';
        $search['status'] = '01';
        return $this->search($search, $field)[0]['count'];
    }

    /**
     *获取角色列表
     */
    public function getRoleList($search = [], $field = '', $rowFrom = 0, $rowTo = 0) {
        $field = !empty($field) ? $field : 'roleid,rolename,memo,rights,issuper';
        $search['status'] = '01';
        $roleInfo = $this->search($search, $field, $rowFrom, $rowTo);

        return ['status' => true, 'message' => '获取成功', 'roleList' => $roleInfo];
    }

    /**
     * 获取角色详细信息
     * 权限直接返回rights字段中的字符串
     */
    public function getRoleInfo($roleId) {

        //检测角色id
        $rule = [
            'roleid|角色ID' => [
                'required', 'int', 'min' => 1
            ]
        ];

        $validate = new Validator($rule);
        $result = $validate->validate([
            'roleid' => $roleId,
        ]);
        if (!$result) {
            $errMessages = $validate->getErrors();
            return ['status' => false, 'message' => '获取错误', 'errorFields' => $errMessages];
        }

        $field = 'roleid,rolename,memo,rights,issuper';
        //$search['rolename'] 为数字时根据roleid精确搜索
        $searchResult = $this->search(['rolename' => $roleId, 'status' => '01'], $field);
        $roleInfo = isset($searchResult[0]) ? $searchResult[0] : [];
        return ['status' => true, 'message' => '获取成功', 'roleInfo' => $roleInfo];
    }

    /**
     * 保存角色信息，修改或者新增
     * @param $roleId
     * @param $roleName
     * @param $rights
     * @param $memo
     * @return array
     */
    public function saveRoleInfo($roleId, $roleName, $rights, $memo) {

        $rule = [
            'rolename|角色名称' => [
                'required', 'hanziAlphaNum',
                'minLength' => '2', 'maxLength' => '20'
            ],
            'memo|备注信息' => [
                'maxLength' => '500'
            ],
        ];

        $validate = new Validator($rule);
        $result = $validate->validate([
            'rolename' => $roleName,
            'memo' => $memo
        ]);
        if (!$result) {
            return ['status' => false, 'message' => '校验失败', 'errorFields' => $validate->getErrors()];
        }

        //权限设置错误，返回错误
        $rightsCount = preg_match_all('/[0,1]+?/', $rights); //权限字符串中0和1的个数
        if (!isset($rights) || strlen($rights) != $this->rightsLength || $rightsCount != $this->rightsLength) {
            return ['status' => false, 'message' => '校验失败', 'errorFields' => ['rights' => '权限设置错误']];
        }

        $nameExist = $this->chkName($roleName, $roleId);
        if (!$nameExist) {
            return ['status' => false, 'message' => '校验失败', 'errorFields' => ['rolename' => '角色名称已存在']];
        }

        if ($roleId > 0) {
            $sql = 'UPDATE Role SET rolename=?,rights=?,memo=?,updatedate=now() WHERE roleid=? AND status=?';
            $var = [$roleName, $rights, $memo, $roleId, '01'];
            $saveResult = Db::update($sql, $var);
        } else {
            $sql = 'INSERT INTO Role(rolename,rights,status,memo,createdate,updatedate) values (?,?,?,?,now(),now())';
            $var = [$roleName, $rights, '01', $memo];
            $saveResult = Db::insert($sql, $var);
        }

        if ($saveResult) {
            return ['status' => true, 'message' => '执行成功'];
        } else {
            return ['status' => false, 'message' => '执行失败'];
        }
    }

    /**
     * 根据角色id删除角色，有关联用户不可删除改角色
     * @param $roleId
     * @return array
     */
    public function deleteRole($roleId) {

        //检测角色id
        $rule = [
            'roleid|角色ID' => [
                'required', 'int', 'min' => 1
            ]
        ];

        $validate = new Validator($rule);
        $result = $validate->validate([
            'roleid' => $roleId,
        ]);
        if (!$result) {
            return ['status' => false, 'message' => '操作失败', 'errorFields' => $validate->getErrors()];
        }

        //删除角色要保证该角色没有关联用户
        $selSql = 'SELECT userid FROM User where roleid=?';
        $selVar = [$roleId];
        $result = Db::selectOne($selSql, $selVar);

        //角色还有绑定的用户，不能删除
        if ($result) {
            return ['status' => false, 'message' => '有关联用户，不能删除角色'];
        }

        //超级管理员不能修改
        $sql = 'UPDATE Role SET status=?,updatedate=now() WHERE roleid=? AND status=? AND issuper = ?';
        $var = ['06', $roleId, '01', 0];
        $result = Db::update($sql, $var);
        if ($result) {
            return ['status' => true, 'message' => '删除角色成功'];
        }
        return ['status' => false, 'message' => '删除角色失败'];
    }

    /**
     * 查询角色信息
     * @param array $search
     * @param $field
     * @param int $rowFrom
     * @param int $rowTo
     * @return array
     */
    private function search($search = [], $field, $rowFrom = 0, $rowTo = 0, $orderBy = '') {
        //只查询有效的角色
        $sql = 'SELECT ' . $field . ' FROM Role';
        $var = [];
        $where = [];
        //超管不展示到前台
        $where[] = 'issuper = ?';
        $var[] = 0;

        //查询角色名/ID
        if (isset($search['rolename']) && !empty($search['rolename'])) {
            $nameParam = $this->searchStringOrNum($search['rolename'], 'rolename', 'roleid');
            $where[] = $nameParam['where'];
            $var = array_merge($var, $nameParam['var']);
        }

        //在职状态
        if (isset($search['status']) && in_array($search['status'], ['01', '06'])) {
            $where[] = 'status = ?';
            $var[] = $search['status'];
        }

        if (!empty($where)) {
            $sql .= ' WHERE ' . implode(' AND ', $where);
        }

        $sql .= empty($orderBy) ? ' ORDER BY roleid DESC' : (' ORDER BY ' . $orderBy);

        return Db::select($sql, $var, $rowFrom, $rowTo);
    }

    /**
     * 检查角色名称
     * @param $roleName
     */
    private function chkName($roleName, $roleId) {
        $sql = 'SELECT roleid FROM Role where rolename = ? and status = ?';
        $var = [$roleName, '01'];
        $roleNameInfo = Db::select($sql, $var);

        if (empty($roleNameInfo)) {
            return true;
        }
        if (count($roleNameInfo) > 1) {
            return false;
        }
        return $roleNameInfo[0]['roleid'] == $roleId;

    }

}